home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1994 / MacHack 1994.toast / MacHack™94 / Hacks / [√] May be freely distributed / Christopher Evans / SF ClickOut / Source / SF ClickOut.c next >
Encoding:
C/C++ Source or Header  |  1994-06-25  |  11.7 KB  |  502 lines  |  [TEXT/KAHL]

  1. /*
  2.     SF ClickOut.c
  3.     
  4.     Example extension. Demonstrates use of PatchWorks trap patching
  5.     system to patch InitApplication. Uses new GenericPatch class.
  6.     
  7.     by Christopher Evans.
  8.     
  9.     © 1994 Natural Intelligence, Inc.
  10. */
  11.  
  12. #include <string.h>
  13. #include <Notification.h>
  14. #include <Traps.h>
  15. #include <stdarg.h>
  16. #include <stdio.h>
  17. #include <stddef.h>
  18. #include <Processes.h>
  19. #include <GestaltEqu.h>
  20. #include <Exception.h>
  21. #include <Extension.h>
  22. #include <GenericPatch.h>
  23. #include "SF ClickOut.h"
  24. #include <SetupA4.h>
  25. #include <LowMem.h>
  26.  
  27.  
  28. static Pack3Patch *thePatch = 0;
  29. static SystemEventPatch *sePatch = 0;
  30. static CloseWindowPatch *cwPatch = 0;
  31. static BringToFrontPatch *btfPatch = 0;
  32.  
  33. #define optionKeyCode 0x003a
  34.  
  35. void ShowIconFamily(short which);
  36.  
  37. extern pascal short    NewDialogHook(short item, DialogPtr theDialog, void *yourDataPtr);
  38. extern pascal short OldDialogHook(short item, DialogPtr theDialog);
  39. extern void    StandardToSFReply(StandardFileReply *newStyle, SFReply *oldStyle);
  40. pascal OSErr DataSelector(OSType selector, long    *response);
  41. void    InstallSelector(void);
  42.  
  43. static int dprintf(const char* format, ...);
  44. Boolean IsPressed(unsigned short k);
  45.  
  46. CloseWindowPatch::CloseWindowPatch()
  47. {
  48.     // initialize instance variables.
  49.     eventPatch = sePatch;
  50.     
  51.     // install the appropriate patch.
  52.     GenericPatch::InitGenericPatch(_CloseWindow, sizeof(CloseWindowParameters));
  53.     Install();
  54.  
  55. void CloseWindowPatch::Behavior()
  56. {
  57.     CloseWindowParameters* params;
  58.     
  59.     WindowPeek        front, tmpFinderWindow;
  60.     
  61.     
  62.     params = (CloseWindowParameters*)itsFrame->parameters;
  63.     
  64.     if(params->theWindow == eventPatch->frontFinderWindow) {
  65.         eventPatch->frontFinderWindow = ((WindowPeek)params->theWindow)->nextWindow;
  66.     }        
  67. }
  68.  
  69. BringToFrontPatch::BringToFrontPatch()
  70. {
  71.     // initialize instance variables.
  72.     GetIndString(finderName,128,1);
  73.     eventPatch = sePatch;
  74.     
  75.     // install the appropriate patch.
  76.     GenericPatch::InitGenericPatch(_BringToFront, sizeof(BringToFrontParameters));
  77.     Install();
  78.  
  79.  
  80. BringToFrontPatch::~BringToFrontPatch()
  81. {
  82.  
  83. }
  84.  
  85.  
  86.  
  87. void BringToFrontPatch::Behavior()
  88. {
  89.     BringToFrontParameters* params;
  90.     
  91.     WindowPeek        front, tmpFinderWindow;
  92.     
  93.     
  94.     params = (BringToFrontParameters*)itsFrame->parameters;
  95.     
  96.     if( *((long *)LMGetCurApName()) ==  *((long *)finderName) ) {
  97.         if(EqualString(LMGetCurApName(), finderName, FALSE, FALSE)) {
  98.             eventPatch->frontFinderWindow = params->itsWindow;
  99.         }
  100.     }
  101. }
  102.  
  103.  
  104. SystemEventPatch::SystemEventPatch()
  105. {
  106.     // initialize instance variables.
  107.     GetIndString(finderName,128,1);
  108.     pack3Patch = thePatch;
  109.     frontFinderWindow = NULL;
  110.     
  111.     // install the appropriate patch.
  112.     GenericPatch::InitGenericPatch(_SystemEvent, sizeof(SystemEventParameters));
  113.     Install();
  114.  
  115. void SystemEventPatch::Behavior()
  116. {
  117.     SystemEventParameters* params;
  118.     
  119.     EventRecord    *evt;
  120.     WindowPeek        front, tmpFinderWindow;
  121.     Handle        wRefCon, windowInfo;
  122.     GrafPtr        savePort;
  123.     Point        mousePoint, localPoint;
  124.     long        dirID;
  125.     short        vRefNum, *shortPtr;        
  126.     StringPtr    curAp = LMGetCurApName();
  127.     
  128.     params = (SystemEventParameters*)itsFrame->parameters;
  129.     evt = params->theEvt;
  130.     
  131.     
  132.     if( *((long *)curAp) ==  *((long *)finderName) ) {
  133.         if(EqualString(curAp, finderName, FALSE, FALSE)) {
  134.             frontFinderWindow = (WindowPtr)LMGetWindowList();
  135.         }
  136.     }
  137.     
  138.     //After it is set, check for mouse downs.  outside of SF dialogs.
  139.     if(evt->what == mouseDown) {
  140.     
  141.     
  142.         front = (WindowPeek)FrontWindow();        //Get the current front window
  143.         if(front!= NULL) {                        //If we got a window
  144.             wRefCon = (Handle)GetWRefCon(front);        //Grab its refcon
  145.             if(wRefCon == (Handle)0x73746466) {            //We're in an SF dialog
  146.                 BlockMove(&evt->where, &mousePoint, 4);
  147.                 localPoint = mousePoint;
  148.                 GetPort(&savePort);
  149.                 SetPort(front);
  150.                 GlobalToLocal(&localPoint);
  151.                 if(!PtInRect(localPoint, &front->port.portRect)) {
  152.                     tmpFinderWindow = frontFinderWindow;
  153.                     while( tmpFinderWindow != NULL) {
  154.                         wRefCon = (Handle)GetWRefCon(tmpFinderWindow);
  155.                         if(wRefCon != 0) {
  156.                             localPoint = mousePoint;
  157.                             
  158.                             SetPort(tmpFinderWindow);
  159.                             GlobalToLocal(&localPoint);
  160.                             if(PtInRect(localPoint, &tmpFinderWindow->port.portRect)) {
  161.                                 windowInfo = (char *)*wRefCon + 8;
  162.                                 if(windowInfo) {
  163.                                     windowInfo = *windowInfo;
  164.                                     windowInfo = *windowInfo + 0x00000030;
  165.                                     dirID = (long)*windowInfo;
  166.                                     windowInfo +=1;
  167.                                     shortPtr = (short *)windowInfo;
  168.                                     vRefNum = (short)*shortPtr;
  169.                                     pack3Patch->SetDirectory(dirID, vRefNum);
  170.                                     
  171.                                     evt->what = nullEvent;
  172.                                     break;
  173.                                 }
  174.                             }
  175.                         }
  176.                         tmpFinderWindow = tmpFinderWindow->nextWindow;
  177.                     }
  178.                 }
  179.                 SetPort(savePort);
  180.             }
  181.         }
  182.     }
  183.     
  184.         
  185. }
  186.  
  187.  
  188.  
  189. Pack3Patch::Pack3Patch()
  190. {
  191.     SysEnvRec    theSERec;
  192.     CursHandle    cursH1, cursH2;
  193.     Size        cs1, cs2;
  194.     short        tmpShort;
  195.     
  196.     // initialize instance variables.
  197.     nextDirID = 0;
  198.     nextVRefNum = 0;
  199.     
  200.     // install the appropriate patch.
  201.     GenericPatch::InitGenericPatch(_Pack3, sizeof(CustomGetParameters));
  202.     Install();
  203. }
  204.  
  205. Pack3Patch::~Pack3Patch()
  206. {
  207.  
  208. }
  209.  
  210. void Pack3Patch::Behavior()
  211. {
  212.     Pack3Parameters        *params = (Pack3Parameters*)itsFrame->parameters;
  213.     SFPutParameters        *sfputParams;
  214.     SFPPutParameters    *sfpputParams;
  215.     SFGetParameters        *sfgetParams;
  216.     SFPGetParameters    *sfpgetParams;
  217.     StandardPutParameters    *standardPutParams;
  218.     StandardGetParameters    *standardGetParams;
  219.     CustomPutParameters    *customPutParams;
  220.     CustomGetParameters    *customGetParams;
  221.     Point where = {-1,-1};
  222.     Point oldWhere = {100,100};
  223.  
  224.  
  225.     switch(params->itsMethod) {
  226.         case 1:            //SFPutFile
  227.             sfputParams = (SFPutParameters*)itsFrame->parameters;
  228.             oldFilter = sfputParams->dlgHook;
  229.             sfputParams->dlgHook = OldDialogHook;
  230.             replyPtr = sfputParams->reply;
  231.         
  232.             break;
  233.         
  234.         case 2:            //SFGetFile
  235.             sfgetParams = (SFGetParameters*)itsFrame->parameters;
  236.  
  237.             oldFilter = sfgetParams->dlgHook;
  238.             sfgetParams->dlgHook = OldDialogHook;
  239.             replyPtr = sfgetParams->reply;
  240.             
  241.             break;
  242.             
  243.         case 3:         //SFPPutFile
  244.             sfpputParams = (SFPPutParameters*)itsFrame->parameters;
  245.  
  246.             oldFilter = sfpputParams->dlgHook;
  247.             sfpputParams->dlgHook = OldDialogHook;
  248.             replyPtr = sfpputParams->reply;
  249.             break;
  250.             
  251.         case 4:            //SFPGetFile
  252.             sfpgetParams = (SFPGetParameters*)itsFrame->parameters;
  253.  
  254.             oldFilter = sfpgetParams->dlgHook;
  255.             sfpgetParams->dlgHook = OldDialogHook;
  256.             replyPtr = sfpgetParams->reply;
  257.             break;
  258.             
  259.         case 5:            //StandardPutFile
  260.             standardPutParams = (StandardPutParameters*)itsFrame->parameters;
  261.  
  262.             {
  263.                 CustomPutPack3ProcPtr        proc;
  264.                 proc = (CustomPutPack3ProcPtr)this->itsOld;
  265.                 
  266.                 proc(standardPutParams->prompt,standardPutParams->defaultName,standardPutParams->reply,sfPutDialogID,where,NewDialogHook,NULL,NULL,NULL,this, 7);
  267.             
  268.             /*
  269.                 An exercise left to the reader...
  270.                 
  271.                 Open the folder in the finder when the option key is pressed 
  272.                 down and a file selected, this way if it isn't openned, they can
  273.                 also see where the file went.  (Remember, the file might not exist 
  274.                 yet...)
  275.             */
  276. //                if( (standardPutParams->reply->sfGood) && (IsPressed(optionKeyCode))) {
  277. //                    OpenSelection(true, &standardPutParams->reply->sfFile);
  278. //                }
  279.             }
  280.                         
  281.             AbortTrap();
  282.             break;
  283.             
  284.         case 6:            //StandardGetFile
  285.             standardGetParams = (StandardGetParameters*)itsFrame->parameters;
  286.  
  287.             {
  288.                 CustomGetPack3ProcPtr        proc;
  289.                 proc = (CustomGetPack3ProcPtr)this->itsOld;
  290.                 this->oldFileFilter = standardGetParams->fileFilter;
  291.                 
  292.                 proc(CustomFileFilter,standardGetParams->numTypes,standardGetParams->typeList,standardGetParams->reply,sfGetDialogID,where,NewDialogHook,NULL,NULL,NULL,this, 8);
  293.                 
  294. //                if( (standardGetParams->reply->sfGood) && (IsPressed(optionKeyCode))) {
  295. //                    OpenSelection(true, &standardGetParams->reply->sfFile);
  296. //                }
  297.             }
  298.             AbortTrap();
  299.             break;
  300.             
  301.         case 7:            //CustomPutFile
  302.             customPutParams = (CustomPutParameters*)itsFrame->parameters;
  303.         
  304.             oldFilter = customPutParams->dlgHook;
  305.             customPutParams->dlgHook = NewDialogHook;
  306.             theirDataPtr = customPutParams->yourDataPtr;
  307.             replyPtr = customPutParams->reply;
  308.             customPutParams->yourDataPtr = (void *)this;
  309.             break;
  310.             
  311.         case 8:            //CustomGetFile
  312.             customGetParams = (CustomGetParameters*)itsFrame->parameters;
  313.         
  314.             oldFilter = customGetParams->dlgHook;
  315.             customGetParams->dlgHook = NewDialogHook;
  316.             theirDataPtr = customGetParams->yourDataPtr;
  317.             replyPtr = customGetParams->reply;
  318.             customGetParams->yourDataPtr = (void *)this;
  319.             break;
  320.     }
  321.     nextDirID = 0;
  322.     nextVRefNum = 0;
  323. }
  324.  
  325.  
  326. void Pack3Patch::SetDirectory(long    dirID, short vRefNum)
  327. {
  328.     nextDirID = dirID;
  329.     nextVRefNum = vRefNum;
  330. }
  331.  
  332. pascal Boolean    CustomFileFilter(ParmBlkPtr    param, void *myData)
  333. {
  334.     Pack3Patch     *p3patch = (Pack3Patch *)myData;
  335.     FileFilterProcPtr    newProc = p3patch->oldFileFilter;
  336.     
  337.     if(newProc==nil) return FALSE;
  338.     
  339.     return (newProc(param));
  340.  
  341. }
  342.  
  343. pascal short NewDialogHook(short item, DialogPtr theDialog, void *yourDataPtr)
  344. {
  345.     StandardFileReply *replyPtr;
  346.     Pack3Patch    *myObject;
  347.  
  348.      myObject = (Pack3Patch    *)yourDataPtr;
  349.     replyPtr = (StandardFileReply *)myObject->replyPtr;
  350.      
  351.     if (myObject->nextDirID != 0) {
  352.         item = sfHookChangeSelection;
  353.         replyPtr->sfFile.vRefNum = myObject->nextVRefNum;  // re-aim standard file at root
  354.         replyPtr->sfFile.parID = myObject->nextDirID;
  355.         replyPtr->sfFile.name[0] = 0;
  356.         
  357.         myObject->nextDirID = 0;
  358.         myObject->nextVRefNum = 0;
  359.     }
  360.      else {
  361.          dlgHookProc    oldDlgHook = myObject->oldFilter;
  362.          
  363.          if(oldDlgHook != NULL) {
  364.              item = oldDlgHook(item, theDialog, myObject->theirDataPtr);
  365.          }
  366.      }
  367.     return item;
  368. }
  369.  
  370. pascal short OldDialogHook(short item, DialogPtr theDialog)
  371. {
  372.     OSErr    gestaltErr;
  373.     long    gestaltResponse;
  374.     Pack3Patch    *myObject;
  375.     gestaltErr = Gestalt('QsfQ', &gestaltResponse);
  376.     
  377.     if((gestaltErr == noErr) && (gestaltResponse != 0)) {
  378.     
  379.         myObject = (Pack3Patch *)gestaltResponse;
  380.         
  381.         if (myObject->nextDirID != 0) {
  382.             item = sfHookRebuildList;    // re-aim standard file at root
  383.             LMSetCurDirStore(myObject->nextDirID);// side-effect is, volume name won't be changed
  384.             LMSetSFSaveDisk(-(myObject->nextVRefNum)); // in upper-right corner...
  385.             
  386.             myObject->nextDirID = 0;
  387.             myObject->nextVRefNum = 0;
  388.         }
  389.          else {
  390.              oldDlgHookProc    oldDlgHook = myObject->oldFilter;
  391.              
  392.              if(oldDlgHook != NULL) {
  393.                  item = oldDlgHook(item, theDialog);
  394.              }
  395.          }
  396.      }
  397.  
  398.     return item;
  399. }
  400.  
  401.  
  402. //
  403. //    Install routine. This is where you allocate your patch objects.
  404. //    Throw an exception if something fails.
  405. //
  406. void Install()
  407. {
  408.     long             theSize;
  409.     short            doIt;
  410.     
  411.     RememberA4();
  412. #ifndef CDEV    
  413.     try {
  414.         //Read preferences to see if we should load
  415.         // if extension succeeds, show happy icon.
  416.         thePatch = new Pack3Patch;        
  417.         sePatch = new SystemEventPatch;    
  418.         cwPatch = new CloseWindowPatch;
  419.         btfPatch = new BringToFrontPatch;
  420.         InstallSelector();
  421.         ShowIconFamily(128);
  422.     } catch {
  423.         // extension failed, show sad icon.
  424.         ShowIconFamily(129);
  425.         throw(theException);
  426.     }
  427. #endif CDEV
  428. }
  429.  
  430. //
  431. //    Remove routine. This is called when system is shutdown.
  432. //    Perhaps this should be removed. Rob thinks it shouldn't even be
  433. //    part of the design.
  434. //
  435.  
  436. void Remove()
  437. {
  438.     Patch::RemoveAll();
  439. }
  440.  
  441. //
  442. // debugging printf.
  443. //
  444.  
  445. static int dprintf(const char* format, ...)
  446. {
  447.     va_list args;
  448.     static char str[256];
  449.     int count;
  450.  
  451. #ifndef CDEV    
  452.     va_start(args, format);
  453.     count = vsprintf(str, format, args);
  454.     va_end(args);
  455.     DebugStr(c2pstr(str));
  456. #endif CDEV    
  457.         
  458.     return count;
  459. }
  460.  
  461. Boolean IsPressed(unsigned short k)
  462. /*
  463.  *  Check to see if key number k is currently held down
  464.  */
  465. {
  466.     unsigned char    km[16];
  467.     
  468.     GetKeys(km);        //Get the KeyMap
  469.     return((km[k>>3]>>(k&7))&1);  //Check required bit
  470. }
  471.  
  472.  
  473.  
  474. pascal OSErr DataSelector(OSType selector, long    *response);
  475. void    InstallSelector(void);
  476.  
  477. void    InstallSelector(void)
  478. {
  479.     OSErr theErr;
  480.     Handle    gestFuncH;
  481.     ProcPtr oldGestaltFunc;
  482.     Str255    theNumStr;
  483.     
  484.     theErr = NewGestalt('QsfQ', (ProcPtr)DataSelector);
  485.     if(theErr != noErr) {
  486.         theErr = ReplaceGestalt('QsfQ', (ProcPtr)DataSelector, oldGestaltFunc);
  487.     }
  488. }
  489.  
  490. pascal OSErr DataSelector(OSType selector, long    *response)
  491. {
  492.     SetUpA4();
  493.     *response = (long)thePatch;
  494.     RestoreA4();
  495.     return noErr;
  496. }
  497.  
  498.  
  499.